from django.db import models
from model_utils import Choices
from django_celery_beat.models import PeriodicTask

# Create your models here.

from aweiuser.models import BaseTable


class Project(BaseTable):
    """
    项目信息表
    """

    class Meta:
        verbose_name = "项目信息"
        db_table = "project"

    name = models.CharField("项目名称", unique=True, null=False, max_length=30)
    desc = models.CharField("项目描述", max_length=100, null=True)
    responsible = models.CharField("创建人", max_length=30, null=False)


class API(BaseTable):
    """
    API信息表
    外键关联project
    """

    class Meta:
        verbose_name = "接口信息"
        db_table = "api"

    # 枚举类型
    ENV_TYPE = ((0, "测试环境"), (1, "生产环境"), (2, "预发布 "))
    TAG = Choices(
        (0, "未知"),
        (1, "成功"),
        (2, "失败"),
        (3, "自动成功"),
        (4, "废弃"),
    )

    name = models.CharField("接口名称", null=False, max_length=100, db_index=True)
    body = models.TextField("主体信息", null=False)
    url = models.CharField("请求地址", null=False, max_length=255, db_index=True)
    method = models.CharField("请求方式", null=False, max_length=10)
    """
        on_delete=models.CASCADE: 表示当关联的 Project 实例被删除时，与该项目相关的所有API也将被删除。
        db_constraint=False 在数据库层面不要强制执行外键约束。这意味着删除 Project 实例时，数据库不会强制要求删除与之关联的 API 实例
        project_id INT,
        FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE
    """
    project = models.ForeignKey(Project, on_delete=models.CASCADE, db_constraint=False)
    relation = models.IntegerField("节点id", null=False)
    delete = models.IntegerField("是否删除", null=True, default=0)
    tag = models.IntegerField("API标签", choices=TAG, default=0)


class Case(BaseTable):
    """
    用例信息表
    关联project
    """

    class Meta:
        verbose_name = "用例信息"
        db_table = "case"

    # 用例枚举
    tag = (
        (1, "冒烟用例"),
        (2, "集成用例"),
        (3, "监控脚本"),
        (4, "核心用例"),
    )
    name = models.CharField("用例名称", null=False, max_length=100)
    project = models.ForeignKey(Project, on_delete=models.CASCADE, db_constraint=False)
    relation = models.IntegerField("节点id", null=False)
    length = models.IntegerField("API个数", null=False)
    tag = models.IntegerField("用例标签", choices=tag, default=2)

    # apis = models.ManyToManyField(API, db_table='api_case', related_name='api_case_relate')

    @property
    def tasks(self):
        """

        这是一个用于获取与用例相关的定时任务的属性。
        具体来说，它查询了 PeriodicTask 模型，找到了描述与项目相关的任务，并返回这些任务的相关信息（id、name、args）。
        在这里，eval(task.pop("args")) 用于将字符串形式的任务参数转换为 Python 对象。最后，它使用 filter 过滤出与当前用例相关的任务。
        :return:
        """
        task_objs = PeriodicTask.objects.filter(description=self.project.id).values(
            "id", "name", "args"
        )
        return filter(lambda task: self.id in eval(task.pop("args")), task_objs)


class CaseStep(BaseTable):
    """
    Test Case Step->表示测试用例的步骤信息
    外键关联用例
    """

    class Meta:
        verbose_name = "用例信息 Step"
        db_table = "case_step"

    name = models.CharField("用例名称", null=False, max_length=100)
    body = models.TextField("主体信息", null=False)
    url = models.CharField("请求地址", null=False, max_length=255)
    method = models.CharField("请求方式", null=False, max_length=10)
    case = models.ForeignKey(Case, on_delete=models.CASCADE, db_constraint=False)
    step = models.IntegerField("顺序", null=False)
    source_api_id = models.IntegerField("api来源", null=False)


class Report(BaseTable):
    """
    报告存储
    外键关联 project

    """
    # 报告类型 和 报告状态 的枚举
    report_type = (
        (1, "调试"),
        (2, "异步"),
        (3, "定时"),
        (4, "部署"),
    )
    report_status = (
        (0, "失败"),
        (1, "成功"),
    )

    class Meta:
        verbose_name = "测试报告"
        db_table = "report"

    name = models.CharField("报告名称", null=False, max_length=100)
    # 对于设置了choice的字段，Django 将为每个字段生成一个以 get_字段名_display 命名的方法，用于获取字段的可读显示值。
    type = models.IntegerField("报告类型", choices=report_type)
    status = models.BooleanField("报告状态", choices=report_status, blank=True)
    summary = models.TextField("报告基础信息", null=False)
    project = models.ForeignKey(Project, on_delete=models.CASCADE, db_constraint=False)


class ReportDetail(models.Model):
    """
    测试报告详情
    一对一关联测试报告
    """

    class Meta:
        verbose_name = "测试报告详情"
        db_table = "report_detail"

    # 建立一对一的关联，确保每个实例只与一个关联实例相关联，on_delete=models.CASCADE: 表示当关联的 Report 实例被删除时，与之关联的当前模型实例也会被级联删除
    # db_constraint=False: 表示在数据库层面不要强制执行外键约束。这意味着删除关联的 Report 实例时，数据库不会强制要求删除与之关联的当前模型实例
    report = models.OneToOneField(
        Report, on_delete=models.CASCADE, null=True, db_constraint=False
    )
    summary_detail = models.TextField("报告详细信息")


class Relation(models.Model):
    """
    树形结构关系
    外键关联项目
    """

    class Meta:
        verbose_name = "树形结构关系"
        db_table = "relation"

    project = models.ForeignKey(Project, on_delete=models.CASCADE, db_constraint=False)
    tree = models.TextField("结构主题", null=False, default=[])
    type = models.IntegerField("树类型", default=1)


class Visit(models.Model):
    METHODS = Choices(
        ("GET", "GET"),
        ("POST", "POST"),
        ("PUT", "PUT"),
        ("PATCH", "PATCH"),
        ("DELETE", "DELETE"),
        ("OPTION", "OPTION"),
    )

    user = models.CharField(max_length=100, verbose_name="访问url的用户名", db_index=True)
    ip = models.CharField(max_length=20, verbose_name="用户的ip", db_index=True)
    project = models.CharField(
        max_length=4, verbose_name="项目id", db_index=True, default=0
    )
    url = models.CharField(max_length=255, verbose_name="被访问的url", db_index=True)
    path = models.CharField(
        max_length=100, verbose_name="被访问的接口路径", default="", db_index=True
    )
    request_params = models.CharField(
        max_length=255, verbose_name="请求参数", default="", db_index=True
    )
    request_method = models.CharField(
        max_length=7, verbose_name="请求方法", choices=METHODS, db_index=True
    )
    request_body = models.TextField(verbose_name="请求体")
    create_time = models.DateTimeField("创建时间", auto_now_add=True, db_index=True)

    class Meta:
        db_table = "visit"


class Config(BaseTable):
    """
    测试用例环境信息表
    https://主机名:端口
    http://主机名:端口
    """

    class Meta:
        verbose_name = "环境信息"
        db_table = "config"

    name = models.CharField("环境名称", null=False, max_length=100)
    body = models.TextField("主体信息", null=False)
    base_url = models.CharField("请求地址", null=False, max_length=100)
    project = models.ForeignKey(Project, on_delete=models.CASCADE, db_constraint=False)
    is_default = models.BooleanField("默认配置", default=False)


class Variables(BaseTable):
    """
    全局变量
    """

    class Meta:
        verbose_name = "全局变量"
        db_table = "variables"

    key = models.CharField(null=False, max_length=100)
    value = models.CharField(null=False, max_length=1024)
    project = models.ForeignKey(Project, on_delete=models.CASCADE, db_constraint=False)
    description = models.CharField("全局变量描述", null=True, max_length=100)
